package com.autonavi.yunda.yunji.core.service.dbfactory;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.Bucket;
import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.autonavi.yunda.yunji.core.enums.DBType;
import com.autonavi.yunda.yunji.core.enums.DatasourceType;
import com.autonavi.yunda.yunji.core.vo.datasource.OssBucketInstance;
import com.autonavi.yunda.yunji.core.vo.datasource.config.OssDataConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * oss工厂
 */
@Repository
@Slf4j
public class OssFactoryService extends AbstractDataSourceFactory<OssBucketInstance> {

    private final Map<String, OSS> ossInstanceMap = new ConcurrentHashMap<>();

    @Override
    public DBType getDbType() {
        return DBType.OSS;
    }

    @Override
    public OssBucketInstance createDataSource(DatasourceType dataSourceType, String dataSourceConfig) {
        OssDataConfig ossDataConfig = JsonUtils.fromOrException(dataSourceConfig, OssDataConfig.class);
        String endpoint = ossDataConfig.getEndpoint();
        String accessKeyId = ossDataConfig.getAk();
        String accessKeySecret = ossDataConfig.getSk();
        String bucket = ossDataConfig.getBucket();
        AmapPreconditions.checkArgument(StringUtils.hasLength(endpoint));
        AmapPreconditions.checkArgument(StringUtils.hasLength(accessKeyId));
        AmapPreconditions.checkArgument(StringUtils.hasLength(accessKeySecret));
        AmapPreconditions.checkArgument(StringUtils.hasLength(bucket));
        if (ossInstanceMap.containsKey(ossDataConfig.getInstanceKey())) {
            return new OssBucketInstance(ossInstanceMap.get(ossDataConfig.getInstanceKey()), bucket);
        }
        ClientBuilderConfiguration ossConf = new ClientBuilderConfiguration();
        ossConf.setSocketTimeout(1000 * 60 * 60 * 6);
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, ossConf);
        ossInstanceMap.put(ossDataConfig.getInstanceKey(), client);
        return new OssBucketInstance(client, bucket);
    }

    @Override
    public void close(OssBucketInstance dataSource) {
        if (dataSource == null) {
            return;
        }
        OSS oss = dataSource.client;
        if (oss != null) {
            oss.shutdown();
        }
    }

    /**
     * 获取指定oss的bucket列表
     */
    public List<String> getOssBucketList(String endpoint, String accessKeyId, String accessKeySecret) {
        ClientBuilderConfiguration ossConf = new ClientBuilderConfiguration();
        ossConf.setSocketTimeout(1000 * 60 * 60 * 6);
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, ossConf);
        List<Bucket> buckets = client.listBuckets();
        client.shutdown();
        List<String> bucketNames = new ArrayList<>();
        buckets.forEach(bucket -> bucketNames.add(bucket.getName()));
        return bucketNames;
    }
}
